package members

import (
	"time"
	"encoding/json"
	"errors"
	"crypto/md5"
	"io"
	"fmt"
	"adai.design/homeserver/db"
)

func GetMembership(id string) *db.Membership {
	return db.GetMembershipById(id)
}

// 邮箱或者手机号
func getMembershipByAccount(account string) *db.Membership {
	return db.GetMembershipByAccount(account)
}

func generateSessionKey() string {
	t := time.Now()
	h := md5.New()
	io.WriteString(h, "adai.design")
	io.WriteString(h, t.String())
	key := fmt.Sprintf("%x", h.Sum(nil))
	return key
}

// Membership 连接方式
// 同一个账号可以在多台设备上进行登录
// 方式一: 账号(手机号/邮箱号) + 密码
// 方式二: ID + Session
// 当用于由账号+密码登录一次之后，再次进行连接时用(ID+Session)的方式
// 账号+密码只在登录的时候使用，账号的HTTP上传，资源的获取都只能通过ID+Session的形式获取
type loginInfo struct {
	Account 	string		`json:"account"`
	Id 			string		`json:"id,omitempty"`
	Password 	string		`json:"password,omitempty"`
	Session 	string		`json:"session,omitempty"`
	Date  		string		`json:"date,omitempty"`
	// 设备类型 ios/android/web/macos
	DevType 	string		`json:"dev_t"`
}

type loginAck struct {
	Id 			string		`json:"id,omitempty"`
	Session 	string		`json:"session,omitempty"`
	Date  		string		`json:"date,omitempty"`
}

var loginFailedError = errors.New("failed")

func login(data []byte) (m *db.Membership, c *db.MembershipClient, err error) {
	var info loginInfo
	err = json.Unmarshal(data, &info)
	if err != nil {
		err = loginFailedError
		return
	}

	if len(info.Account) != 0 {
		m = getMembershipByAccount(info.Account)
		if m == nil {
			err = loginFailedError
			return
		}
		if m.Password == info.Password {
			// 断开原先的同类型设备的链接
			for i, c := range m.Clients {
				if c.DevType == info.DevType {
					m.Clients = append(m.Clients[:i], m.Clients[i+1:]...)
				}
			}
			// 新加入的链接
			c = &db.MembershipClient{
				DevType: info.DevType,
				Session: generateSessionKey(),
				Last: time.Now(),
			}
			m.Clients = append(m.Clients, c)
			m.Save()
			return
		}
		err = loginFailedError
		return

	} else if len(info.Id) != 0 {
		m = db.GetMembershipById(info.Id)
		if m == nil {
			err = loginFailedError
			return
		}

		for _, c = range m.Clients {
			if c.Session == info.Session && c.DevType == info.DevType{
				c.Last = time.Now()
				c.Badge = 0
				err = nil
				m.Save()
				return
			}
		}

		err = loginFailedError
		return
	}
	err = loginFailedError
	return
}








